package com.singbon.server.security;
import com.alibaba.fastjson.JSON;
import com.singbon.server.util.DesUtil;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
/**
 */
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
  @Resource
  private CustomUserDetailsService customUserDetailsService;
  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String inputName = null;
    String inputPassword = null;
    try {
      inputName = DesUtil.encrypt(authentication.getName());
      inputPassword = DesUtil.encrypt(authentication.getCredentials().toString());
    }
    catch (Exception e) {
      e.printStackTrace();
    }
    // 获取用户输入的用户名和密码
    // String inputName = authentication.getName()
    // String inputPassword = authentication.getCredentials().toString()

    CustomWebAuthenticationDetails details = (CustomWebAuthenticationDetails) authentication.getDetails();
    /* ======================== */
    Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
    for (GrantedAuthority authority : authorities) {
      System.out.println("authority = " + authority.toString());
      System.out.println("authority = " + authority.getAuthority());
    }
    Object principal = authentication.getPrincipal();
    System.out.println("principal = " + principal);
    /* ======================== */
    String verifyCode = details.getVerifyCode();
    //这里调验证码的对比
    if (!validateVerify(verifyCode)) {
      throw new DisabledException("验证码输入错误");
    }
    // userDetails为数据库中查询到的用户信息
    System.out.println("inputName = " + inputName);
    UserDetails userDetails = customUserDetailsService.loadUserByUsername(inputName);
    System.out.println("userDetails = " + userDetails);
    System.out.println("userDetails = " + JSON.toJSONString(userDetails));
    System.out.println("userDetails = " + userDetails.getPassword());
    // 这里直接偷懒手动密码校验了，也可以通过注入 passwordEncode 实现
    boolean passwdIsOk = userDetails.getPassword().equals(inputPassword);
    System.out.println("passwdIsOk = " + passwdIsOk);
    if (!passwdIsOk) {
      throw new BadCredentialsException("密码错误");
    }
    //System.out.println("inputName = " + inputName)
    return new UsernamePasswordAuthenticationToken(inputName, inputPassword, userDetails.getAuthorities());
  }
  /**
   * 验证码的对比方式
   */
  private boolean validateVerify(String inputVerify) {
    //获取当前线程绑定的request对象
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    String validateCodeParaName = "validateCode";
    // 不分区大小写
    // 这个validateCode是在servlet中存入session的名字
    if (null != request.getSession() && null != request.getSession().getAttribute(validateCodeParaName)) {
      String validateCode = ((String) request.getSession().getAttribute(validateCodeParaName)).toLowerCase();
      System.out.println("验证码：" + validateCode + "用户输入：" + inputVerify);
      inputVerify = inputVerify.toLowerCase();
      //加入验证码时用传过来的进行对比
      // return validateCode.equals(inputVerify)
      //这里自己和自己对比
      return validateCode.equals(validateCode);
    }
    else {
      return false;
    }
  }
  @Override
  public boolean supports(Class<?> authentication) {
    // 这里不要忘记，和UsernamePasswordAuthenticationToken比较
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
  }
}
